//
//  BYScanView.swift
//  BYScan
//
//  Created by yetupal on 2023/6/28.
//

import UIKit


class BYScanMaskView: UIView {
    
    
    /// 默认扫码区域为正方形，如果扫码区域不是正方形，设置宽高比
    var whRatio: CGFloat = 1.0
    /// 矩形框(视频显示透明区)域向上移动偏移量，0表示扫码透明区域在当前视图中心位置，如果负值表示扫码区域下移
    var centerUpOffset: CGFloat = 44
    /// 矩形框(视频显示透明区)域离界面左边及右边距离，默认60
    var xScanRetangleOffset: CGFloat = 60
    // 扫码区域
    var scanRetangleRect = CGRect.zero
    
    // 网格扫码动画封装
    private var scanNetAnimation: BYScanAnimationView?
    
    // 记录动画状态
    var isAnimationing = false
    
    /*
     // Only override draw() if you perform custom drawing.
     // An empty implementation adversely affects performance during animation.
     override func draw(_ rect: CGRect) {
     // Drawing code
     }
     */
    
    override init(frame: CGRect) {
        
        // 扫描网格动画
        scanNetAnimation = BYScanAnimationView.instance()
        var frameTmp = frame
        frameTmp.origin = CGPoint.zero
        
        super.init(frame: frameTmp)
        
        backgroundColor = UIColor.clear
    }
    
    public required init?(coder aDecoder: NSCoder) {
        self.init()
    }
    
    deinit {
        
        print("释放资源 ==》 \(self.classForCoder)")
        
        if scanNetAnimation != nil {
            scanNetAnimation!.stopStepAnimating()
        }
    }
    
    
    // 开始扫描动画
    func startScanAnimation() {
        guard !isAnimationing else {
            return
        }
        isAnimationing = true
        
        
        scanNetAnimation?.startAnimatingWithRect(animationRect: BYScanStyle.defaultServie.scanningArea(),
                                                 parentView: self,
                                                 image: bbModularImage("icon_scan_full_line"))
    }
    
    // 开始扫描动画
    func stopScanAnimation() {
        isAnimationing = false
        
        scanNetAnimation?.stopStepAnimating()
    }
    
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    open override func draw(_ rect: CGRect) {
        drawScanRect()
    }
    
    //MARK: ----- 绘制扫码效果-----
    func drawScanRect() {
        /// 矩形框(视频显示透明区)域离界面左边及右边距离，默认60
        let XRetangleLeft: CGFloat = BYScanStyle.defaultServie.scanningArea().origin.x
        let sizeRetangle = BYScanStyle.defaultServie.scanningArea().size
        
        // 扫码区域Y轴最小坐标
        let YMinRetangle = BYScanStyle.defaultServie.scanningArea().origin.y
        let YMaxRetangle = YMinRetangle + sizeRetangle.height
        let XRetangleRight = frame.size.width - XRetangleLeft
        
        guard let context = UIGraphicsGetCurrentContext() else { return }
        
        // 非扫码区域半透明
        // 设置非识别区域颜色
        context.setFillColor(BYScanStyle.defaultServie.coverColor.cgColor)
        // 填充矩形
        // 扫码区域上面填充
        var rect = CGRect(x: 0, y: 0, width: frame.size.width, height: YMinRetangle)
        context.fill(rect)
        
        // 扫码区域左边填充
        rect = CGRect(x: 0, y: YMinRetangle, width: XRetangleLeft, height: sizeRetangle.height)
        context.fill(rect)
        
        // 扫码区域右边填充
        rect = CGRect(x: XRetangleRight, y: YMinRetangle, width: XRetangleLeft, height: sizeRetangle.height)
        context.fill(rect)
        
        // 扫码区域下面填充
        rect = CGRect(x: 0, y: YMaxRetangle, width: frame.size.width, height: frame.size.height - YMaxRetangle)
        context.fill(rect)
        // 执行绘画
        context.strokePath()
        
        // 中间画矩形(正方形)
        /// 矩形框线条颜色，默认白色
        context.setStrokeColor(BYScanStyle.defaultServie.lineColor.cgColor)
        /// 矩形框线条宽度，默认1
        context.setLineWidth(1)
        context.addRect(CGRect(x: XRetangleLeft, y: YMinRetangle, width: sizeRetangle.width, height: sizeRetangle.height))
        
        
        context.strokePath()
        
        scanRetangleRect = CGRect(x: XRetangleLeft, y: YMinRetangle, width: sizeRetangle.width, height: sizeRetangle.height)
        
        
        // 画矩形框4格外围相框角
        
        // 相框角的宽度和高度
        let wAngle: CGFloat = 24
        let hAngle: CGFloat = 24
        
        // 4个角的 线的宽度
        /// 扫码区域4个角的线条宽度,默认6，建议8到4之间
        let linewidthAngle: CGFloat = 6 // 经验参数：6和4
        
        // 画扫码矩形以及周边半透明黑色坐标参数
        var diffAngle: CGFloat = linewidthAngle / 3
        diffAngle = linewidthAngle / 2 // 框外面4个角，与框有缝隙
        diffAngle = linewidthAngle / 2 // 框4个角 在线上加4个角效果
        diffAngle = 0 // 与矩形框重合
        
        diffAngle = linewidthAngle / 3 // 框外面4个角，与框紧密联系在一起
        
        /// 4个角的颜色
        context.setStrokeColor(BYScanStyle.defaultServie.hornColor.cgColor)
        context.setFillColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
        
        // Draw them with a 2.0 stroke width so they are a bit more visible.
        context.setLineWidth(linewidthAngle)
        
        
        //
        let leftX = XRetangleLeft - diffAngle
        let topY = YMinRetangle - diffAngle
        let rightX = XRetangleRight + diffAngle
        let bottomY = YMaxRetangle + diffAngle
        
        // 左上角水平线
        context.move(to: CGPoint(x: leftX - linewidthAngle / 2, y: topY))
        context.addLine(to: CGPoint(x: leftX + wAngle, y: topY))
        
        // 左上角垂直线
        context.move(to: CGPoint(x: leftX, y: topY - linewidthAngle / 2))
        context.addLine(to: CGPoint(x: leftX, y: topY + hAngle))
        
        // 左下角水平线
        context.move(to: CGPoint(x: leftX - linewidthAngle / 2, y: bottomY))
        context.addLine(to: CGPoint(x: leftX + wAngle, y: bottomY))
        
        // 左下角垂直线
        context.move(to: CGPoint(x: leftX, y: bottomY + linewidthAngle / 2))
        context.addLine(to: CGPoint(x: leftX, y: bottomY - hAngle))
        
        // 右上角水平线
        context.move(to: CGPoint(x: rightX + linewidthAngle / 2, y: topY))
        context.addLine(to: CGPoint(x: rightX - wAngle, y: topY))
        
        // 右上角垂直线
        context.move(to: CGPoint(x: rightX, y: topY - linewidthAngle / 2))
        context.addLine(to: CGPoint(x: rightX, y: topY + hAngle))
        
        // 右下角水平线
        context.move(to: CGPoint(x: rightX + linewidthAngle / 2, y: bottomY))
        context.addLine(to: CGPoint(x: rightX - wAngle, y: bottomY))
        
        // 右下角垂直线
        context.move(to: CGPoint(x: rightX, y: bottomY + linewidthAngle / 2))
        context.addLine(to: CGPoint(x: rightX, y: bottomY - hAngle))
        
        context.strokePath()
    }
}



fileprivate class BYScanAnimationView: UIImageView {
    
    var isAnimationing = false
    var animationRect = CGRect.zero
    
    /*
     // Only override draw() if you perform custom drawing.
     // An empty implementation adversely affects performance during animation.
     override func draw(_ rect: CGRect) {
     // Drawing code
     }
     */
    
    func startAnimatingWithRect(animationRect: CGRect, parentView: UIView, image: UIImage?) {
        self.image = image
        self.animationRect = animationRect
        parentView.addSubview(self)
        
        isHidden = false
        isAnimationing = true
        if image != nil {
            stepAnimation()
        }
    }
    
    @objc func stepAnimation() {
        guard isAnimationing else {
            return
        }
        var frame = animationRect
        let hImg = image!.size.height * animationRect.size.width / image!.size.width
        
        frame.origin.y -= hImg
        frame.size.height = hImg
        self.frame = frame
        alpha = 0.0
        
        UIView.animate(withDuration: 1.4, animations: {
            self.alpha = 1.0
            var frame = self.animationRect
            let hImg = self.image!.size.height * self.animationRect.size.width / self.image!.size.width
            frame.origin.y += (frame.size.height - hImg)
            frame.size.height = hImg
            self.frame = frame
        }, completion: { _ in
            self.perform(#selector(BYScanAnimationView.stepAnimation), with: nil, afterDelay: 0.3)
        })
    }
    
    func stopStepAnimating() {
        isHidden = true
        isAnimationing = false
    }
    
    static func instance() -> BYScanAnimationView {
        return BYScanAnimationView()
    }
    
    deinit {
        stopStepAnimating()
    }
    
}
